﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Threading;
using System.Windows;
using FxSuperCore.Log;
using FxWinSuper.Functions;
using FxWinSuper.UI.Menu.Pages;

namespace FxWinSuper.Plugin.Extension
{
	public static class PluginHelper
	{
		private static Dictionary<string, ILogPrint> LoggerDic = new Dictionary<string, ILogPrint>();

		private static ILogPrint Logger = InternalLog.Instance;

		/// <summary>
		/// 所有插件加载完成事件
		/// </summary>
		public static event Action PluginLoadComplete
		{
			add => PluginController.PluginLoadComplete += value;
			remove => PluginController.PluginLoadComplete -= value;
		}

		/// <summary>
		/// 收到程序启动时传递的命令行参数事件，当多次启动程序时，后启动的程序只会传递命令行参数
		/// </summary>
		public static event Action<string[]> OnReceiveApplicationStartupCommandLine
		{
			add => (Application.Current as App).OnReceiveAppStartCommandLine += value;
			remove => (Application.Current as App).OnReceiveAppStartCommandLine -= value;
		}

		internal static void AssertAccessThreadIsMain()
		{
			Thread currentThread = Thread.CurrentThread;
			if (currentThread.Name != MainWindow.MainThreadName || currentThread.ManagedThreadId != 1)
			{
				throw new AccessViolationException("该方法限制主线程访问");
			}
		}

		/// <summary>
		/// 从调用当前方法的堆栈中获取来源插件信息
		/// </summary>
		internal static PluginInfo GetCurrentPluginContext()
		{
			StackTrace stackTrace = new StackTrace();
			foreach (StackFrame stackFrame in stackTrace.GetFrames())
			{
				Assembly assembly = stackFrame.GetMethod().DeclaringType.Assembly;
				WinSupperPluginAttribute winSupperPluginAttribute = assembly.GetCustomAttribute<WinSupperPluginAttribute>();
				if (winSupperPluginAttribute == null)
				{
					continue;
				}

				PluginInfo plugin = PluginController.GetPluginByAttribute(winSupperPluginAttribute);
				if (plugin != null)
				{
					return plugin;
				}
			}

			return null;
		}

		/// <summary>
		/// 获取当前插件的日志打印（只允许在插件中调用）
		/// </summary>
		/// <returns>日志打印</returns>
		public static ILogPrint GetCurrentLogPrint()
		{
			PluginInfo pluginInfo = GetCurrentPluginContext();
			if (pluginInfo == null)
			{
				throw new Exception("未获取到当前插件的插件信息");
			}

			lock (LoggerDic)
			{
				if (!LoggerDic.ContainsKey(pluginInfo.PluginName))
				{
					LoggerDic[pluginInfo.PluginName] = new PluginLoggerPrinter(pluginInfo.PluginName, Logger);
				}
			}

			return LoggerDic[pluginInfo.PluginName];
		}

		/// <summary>
		/// 将指定操作转移到Ui线程
		/// </summary>
		/// <param name="delegate">操作委托</param>
		public static void RunOnUiThread(Action @delegate)
		{
			MainWindow.Instance.Invoke(@delegate);
		}

		/// <summary>
		/// 安装插件商店
		/// </summary>
		/// <param name="store">插件商店</param>
		public static void InstallPluginStore(IPluginStore store)
		{
			AssertAccessThreadIsMain();
			if (store == null)
			{
				throw new NullReferenceException("插件商店不可为null");
			}

			PluginInfo pluginInfo = GetCurrentPluginContext();
			if (pluginInfo != null && !pluginInfo.PluginAssembleInfo.BootStrapPlugin)
			{
				throw new Exception("只有标记为BootStrapPlugin的插件才可以设置插件商店");
			}

			if (pluginInfo != null && PluginPageViewModel.Instance.PluginStore != null)
			{
				Logger.Warnning("已经存在插件商店功能，设置失败");
				return;
			}

			PluginPageViewModel.Instance.PluginStore = store;
			Logger.Info($"插件[{pluginInfo?.PluginName}]正在提供插件服务");
		}
	}
}
